package com.gongyibao.gbase.support;

import com.gongyibao.gbase.config.JedisConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.params.SetParams;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * redis工具类
 */
@Slf4j
@Component
public class RedisUtils {
    private static final String LOCK_SUCCESS = "OK";
    /**
     * //锁不存在新增，存在不做任何操作
     */
    private static final String SET_IF_NOT_EXIST = "NX";
    /**
     * //秒，PX:毫秒
     */
    private static final String SET_WITH_EXPIRE_TIME = "EX";
    private static final Long RELEASE_SUCCESS = 1L;

    @Autowired
    private JedisConfig config;

    private static JedisSentinelPool jedisSentinelPool = null;

    @PostConstruct
    public void autoInit() {
        if (!config.autoInit) {
            return;
        }
        initRedis();
    }

    public void initRedis() {
        try {
            if (null == jedisSentinelPool) {
                JedisPoolConfig poolConfig = new JedisPoolConfig();
                poolConfig.setMaxTotal(config.maxActive);
                poolConfig.setMaxIdle(config.maxIDLE);
                poolConfig.setMaxWaitMillis(config.maxWait);

                Set<String> set = new HashSet<>();
                String[] nodes = config.host.split(",");
                for (String node : nodes) {
                    set.add(node);
                }

                jedisSentinelPool = new JedisSentinelPool(config.serverName,
                        set, poolConfig, 0, 0, null, 0, null,
                        0, 0, config.password, null);
            }
        } catch (Exception e) {
            log.error("初始化redis报错：" + e.getMessage());
        }
    }

    public static Jedis getJedis() {
        return jedisSentinelPool.getResource();
    }

    public static void close(Jedis jedis) {
        jedis.close();
    }

    private RedisUtils() {
    }

    public static String get(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = getJedis();
            result = jedis.get(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
            return result;
        }
    }

    public static void set(String key, String value, Integer time) {
        Jedis jedis = null;
        try {
            value = StringUtils.isBlank(value) ? "" : value;
            jedis = getJedis();
            if (time != 0) {
                jedis.setex(key, time, value);
            } else {
                jedis.set(key, value);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public static void del(String key) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.del(key);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 尝试获取分布式锁
     *
     * @param lockKey    锁
     * @param requestId  请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) {
        Jedis jedis = null;
        boolean result = false;
        try {
            jedis = getJedis();
            SetParams setParams = SetParams.setParams().ex(expireTime).nx();
            String result2 = jedis.set(lockKey, requestId, setParams);
            if (LOCK_SUCCESS.equals(result2)) {
                result = true;
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
            return result;
        }

    }


    /**
     * 释放分布式锁
     *
     * @param lockKey   锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(String lockKey, String requestId) {
        Jedis jedis = null;
        boolean result = false;
        try {
            jedis = getJedis();
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            Object result2 = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
            if (RELEASE_SUCCESS.equals(result2)) {
                result = true;
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
            return result;
        }

    }

}
